﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace VisualGTest.Binding
{
    /// <summary>
    /// The result implementation paired with the Runner's BeginTestRun() and
    /// EndTestRun() methods.
    /// </summary>
    internal class TestRunAsyncResult : IAsyncResult
    {
        private AsyncCallback m_callback;

        #region property backing variables

        private TestRunAsyncState _state;
        private ManualResetEvent _waitHandle;
        private bool _completedSynchronously;
        private bool _isCompleted;

        #endregion

        #region IAsyncResult Members

        public object AsyncState
        {
            get { return _state; }
        }

        public WaitHandle AsyncWaitHandle
        {
            get
            {
                if (_waitHandle == null)
                {
                    _waitHandle = new ManualResetEvent(false);

                    if (this.IsCompleted)
                    {
                        _waitHandle.Set();
                    }
                }

                return _waitHandle;
            }
        }

        public bool CompletedSynchronously
        {
            get { return _completedSynchronously; }
        }

        public bool IsCompleted
        {
            get { return _isCompleted; }
        }

        #endregion

        public TestRunAsyncResult(AsyncCallback callback, TestRunAsyncState state)
        {
            m_callback = callback;
            _state = state;
            _waitHandle = null;
            _completedSynchronously = false;
            _isCompleted = false;
        }

        /// <summary>
        /// Modeled from System.IO.Pipes.PipeAsyncResult .
        /// </summary>
        internal void CallUserCallback()
        {
            if (m_callback != null)
            {
                _completedSynchronously = false;
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.CallUserCallbackWorker));
            }
            else
            {
                _isCompleted = true;

                if (this._waitHandle != null)
                {
                    this._waitHandle.Set();
                }
            }
        }

        /// <summary>
        /// Calls the asynchronous callback. This result object is passed into
        /// the callback.
        /// </summary>
        /// <param name="callbackState"></param>
        private void CallUserCallbackWorker(object callbackState)
        {
            _isCompleted = true;

            if (this._waitHandle != null)
            {
                this._waitHandle.Set();
            }

            m_callback(this);
        }
    }
}
